﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#include "GbmpActionCreatePointFamilyInstance.h"
#include "IPickFilter.h"
#include "IElement.h"
#include "IGraphicsBRepFace.h"
#include "IDocument.h"
#include "IInstance.h"
#include "IElementPosition.h"
#include "IReferencePlane.h"
#include "GraphicsNodeAndTransform.h"
#include "IGraphicsNodeReference.h"
#include "IElementModelShape.h"
#include "IGraphicsElementShape.h"
#include "IPickTarget.h"
#include "GraphicsNodeUtils.h"
#include "IElementBasicInformation.h"
#include "IMainWindow.h"
#include "IUiView.h"

#include "IUiDocument.h"
#include "IUiDocumentViewManager.h"
#include "UserTransactionGroupUtils.h"
#include "ICommandButtonDefinition.h"
#include "GcmpCommandNames.h"
#include "ISelection.h"
#include "IRibbonGroup.h"
#include "IUserTransaction.h"
#include "IModelView.h"
#include "IGraphicsPlane.h"
#include "IHighlights.h"
#include "IPlane.h"
#include "AlgorithmIntersect.h"
#include "IGraphicsLine.h"
#include "ICamera.h"
#include "GbmpModelViewUtil.h"
#include "ILine3d.h"
#include "Coordinate3d.h"
#include "IOnePointInstanceInput.h"
#include "IPickPointAction.h"
#include "LevelUtils.h"
#include "PickNodeReferenceOption.h"
#include "IPickNodeReferenceAction.h"
#include "IPickCandidates.h"
#include "ContainerUtil.h"
#include "IPick.h"
#include "AlgorithmProject.h"
#include "IElementPositionPoints.h"
#include "IRegenerator.h"
#include "IGraphicsNodeGroup.h"
#include "IGraphicsStyleManager.h"
#include "GcmpBuiltInCategoryUniIdentities.h"
#include "GbmpMoveUtils.h"
#include "IElementStatus.h"
#include "GbmpGraphicsNodeUtils.h"
#include "IGraphicsBRepBody.h"
#include "ICanvas.h"
#include "GbmpUiPlatformCommandIds.h"
#include "GbmpControlIds.h"
#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"

using namespace gcmp;



namespace
{
    ElementId GetWorkLevelId(IDocument* pDoc, IModelView* pModelView)
    {
        //关联的面不是参照平面时，关联到标高
        // 老的标高等新的结构构件都完成后， 需要去掉
        //GmModelViewUtil::GetWorkLevelId内存在对老的视图的兼容，现在换成GbmpModelViewUtil，老视图下慎用！
        ElementId baseId = GbmpModelViewUtil::GetWorkLevelId(pModelView);
        if (!baseId.GetIsValidId())
        {
            baseId = GbmpModelViewUtil::GetLowestLevelId(pDoc);
        }
        // 新标高和新视图
        if (!baseId.IsValid())
        {
            baseId = GbmpModelViewUtil::GetWorkLevelId(pModelView);
        }
        if (!baseId.IsValid())
        {
            std::vector<const ILevel*> pLevels = LevelUtils::GetLevelsFromLowToHigh(pDoc);
            if (pLevels.size() > 0)
            {
                baseId = pLevels[0]->GetOwnerElement()->GetElementId();
            }
        }
        return baseId;
    }
}
gcmp::Vector3d GetMousePointOnPlane(gcmp::IUiView* pCurrentView, gcmp::IGraphicsPlane* pPlane, const gcmp::Vector3d& mousePt)
{
    DBG_WARN_AND_RETURN_UNLESS(pCurrentView != nullptr, Vector3d::Zero, L"当前pCurrentView为空",L"GDMPLab",L"2024-03-30");
    DBG_WARN_AND_RETURN_UNLESS(pPlane, Vector3d::Zero, L"当前pPlane为空",L"GDMPLab",L"2024-03-30");
    ICanvas *pCanvas = pCurrentView->GetCanvas();
    DBG_WARN_AND_RETURN_UNLESS(pCanvas != nullptr, Vector3d::Zero, L"pCanvas为空",L"GDMPLab",L"2024-03-30");
    gcmp::ICamera* pCamera = pCanvas->GetCamera();
    DBG_WARN_AND_RETURN_UNLESS(pCamera, Vector3d::Zero, L"pCamera为空",L"GDMPLab",L"2024-03-30");
    Vector3d cameraDir = pCamera->GetDirection();
    gcmp::OwnerPtr<gcmp::IGraphicsLine> opMouseRay = gcmp::IGraphicsLine::CreateByParametric(mousePt, gcmp::Vector3d::Create(cameraDir.X(), cameraDir.Y(), cameraDir.Z()), gcmp::Intervald::Create(0, 1000));
    Vector3d pointOnPlane;
    if (!AlgorithmIntersect::Intersect(static_cast<const ILine3d*>(opMouseRay->GetGeometry()), pPlane->GetGmIPlane(), pointOnPlane))
        return Vector3d::Zero;
    return pointOnPlane;
}
//////////////////////////////////////////////////////////////////////////
class SetupRelatedPlanePickFaceFilter : public gcmp::IPickFilter
{
public:
    SetupRelatedPlanePickFaceFilter(gcmp::IDocument* pDocument);
    virtual ~SetupRelatedPlanePickFaceFilter();
    virtual bool AllowElement(const gcmp::ElementId& elementID) const override;
    virtual bool AllowGraphicsNode(const gcmp::IGraphicsNodeReference& nodeReference) const override;
    virtual bool SetPickTargetOption(gcmp::IPickTarget* pickTarget) override;

    void SetDisabledElements(const std::vector<gcmp::ElementId> &sourceElementIds);

protected:
    const IDocument* GetDocument() const { return m_pDoc; }
private:
    std::vector<gcmp::ElementId> m_vecDisabledElementIds;
    gcmp::IDocument* m_pDoc;
};

////////////////////////////////////////////////////////////////////////////
SetupRelatedPlanePickFaceFilter::SetupRelatedPlanePickFaceFilter(IDocument* pDocument)
    :m_pDoc(pDocument)
{
}

SetupRelatedPlanePickFaceFilter::~SetupRelatedPlanePickFaceFilter()
{
}

bool SetupRelatedPlanePickFaceFilter::AllowElement(const ElementId& elementID) const
{
    IElement* pElement = GetDocument()->GetElement(elementID);
    if (pElement == nullptr || pElement->GetBasicInformation()->GetIsTransient())
    {
        return false;
    }

    if (std::find(m_vecDisabledElementIds.begin(), m_vecDisabledElementIds.end(), elementID) != m_vecDisabledElementIds.end())
    {
        return false;
    }
    ElementId planeIdLockedTo;
    //FamGeneralForm相关内部类这里不做API替换处理，外部根据情况做相应处理
    /*if (IsA<FamGeneralForm>(pElement))
    {
        FamGeneralForm *pForm = dynamic_cast<FamGeneralForm*>(pElement);
        planeIdLockedTo = pForm->GetLockedPlaneId();
    }*/
    if (IsA<IInstance>(pElement))
    {
        const IInstance *pInstance = dynamic_cast<IInstance*>(pElement);
        const IElementPosition *posBehavior = pInstance->GetElementPosition();
        if (posBehavior != nullptr)
        {
            planeIdLockedTo = posBehavior->GetBaseAssociatedPlaneId();
        }
    }
    if (planeIdLockedTo.IsValid())
    {
        const IReferencePlane* pRefPlane = dynamic_cast<IReferencePlane*>(GetDocument()->GetElement(planeIdLockedTo));
        if (pRefPlane != nullptr)
        {
            OwnerPtr<gcmp::IGraphicsNodeReference> opRefObj = pRefPlane->GetReferencedObject();
            if (opRefObj != nullptr)
            {
                ElementId idRefElement = opRefObj->GetElementId();
                if (std::find(m_vecDisabledElementIds.begin(), m_vecDisabledElementIds.end(), idRefElement) != m_vecDisabledElementIds.end())
                {
                    return false;
                }
            }
        }
    }
    return true;
}

bool SetupRelatedPlanePickFaceFilter::AllowGraphicsNode(const gcmp::IGraphicsNodeReference& nodeReference) const
{
    OwnerPtr<GraphicsNodeAndTransform> opGNode;
    const IElement* pElement = GetDocument()->GetElement(nodeReference.GetElementId());
    DBG_WARN_AND_RETURN_UNLESS(pElement, nullptr, L"nodeReference指向的构件找不到！",L"GDMPLab",L"2024-03-30");
    const IGraphicsElementShape* pModelGRep = nullptr;
    pModelGRep = pElement->GetElementModelShape()->GetGraphicsElementShape();
    //没有模型GRep
    if (!pModelGRep)
        return false;
    opGNode = GraphicsNodeUtils::GetGraphicsNodeAndTransform(GetDocument(), pModelGRep, nodeReference.GetGraphicsNodeIdPath());
    if (opGNode == nullptr)
        return false;
    const IGraphicsBRepFace* pGFace = dynamic_cast<const IGraphicsBRepFace*>(opGNode->m_wpGraphicsNode.Get());
    if (pGFace)
    {
        //所有的平面都可以拾取
        if (pGFace->IsPlanar())
        {
            return true;
        }
    }
    return false;
}

bool SetupRelatedPlanePickFaceFilter::SetPickTargetOption(gcmp::IPickTarget* pickTarget)
{
    pickTarget->DisableAll();
    pickTarget->EnableFace();
    return true;
}
void SetupRelatedPlanePickFaceFilter::SetDisabledElements(const std::vector<gcmp::ElementId> &sourceElementIds)
{
    m_vecDisabledElementIds.clear();
    m_vecDisabledElementIds.insert(m_vecDisabledElementIds.begin(), sourceElementIds.begin(), sourceElementIds.end());
}
////////////////////////////////////////////////////////////////////////////

ActionCreatePointFamilyInstance::ActionCreatePointFamilyInstance(EnWayToSetupRelatedPlane eWayToSetup, const gcmp::ElementId& familyId, const std::wstring& familyType)
    : m_isUserCancelled(false)
    , m_eWayToSetup(eWayToSetup)
    , m_nTransactionGroupId(-1)
    , m_familyId(familyId)
    , m_familyType(familyType)
    , m_idNewInstance(ElementId::InvalidID)
{
}

ActionCreatePointFamilyInstance::~ActionCreatePointFamilyInstance()
{
    if (m_nTransactionGroupId >= 0)
    {
        IUiView* pCurrentView = IUiDocumentViewManager::Get()->GetCurrentUiView();
        DBG_WARN_AND_RETURN_VOID_UNLESS(pCurrentView != nullptr, L"GetCurrentUiView()为空",L"GDMPLab",L"2024-03-30");
        IUiDocument* pUiDoc = pCurrentView->GetUiDocument();
        DBG_WARN_AND_RETURN_VOID_UNLESS(pUiDoc, L"pUiDoc为空",L"GDMPLab",L"2024-03-30");
        IDocument* pDoc = pUiDoc->GetDbDocument();
        DBG_WARN_AND_RETURN_VOID_UNLESS(pDoc, L"无效的文档",L"GDMPLab",L"2024-03-30");
        UserTransactionGroupUtils::Abort(pDoc, m_nTransactionGroupId);
    }
}

void ActionCreatePointFamilyInstance::InitAction(IUiView* pCurrentView)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(pCurrentView != nullptr, L"GetCurrentUiView()为空",L"GDMPLab",L"2024-03-30");
    IUiDocument* pUiDoc = pCurrentView->GetUiDocument();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pUiDoc, L"pUiDoc为空",L"GDMPLab",L"2024-03-30");
    IDocument* pDoc = pUiDoc->GetDbDocument();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDoc, L"无效的文档",L"GDMPLab",L"2024-03-30");
    ISelection::Get()->Clear(pDoc);
    IHighlights::Get()->Clear();
    SelectPosition(pCurrentView);
}

void ActionCreatePointFamilyInstance::OnChildActionFinished(IUiView* pCurrentView, const ActionOutput& childActionReturnParam)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(nullptr != pCurrentView, L"pCurrentView为空",L"GDMPLab",L"2024-03-30");
    IUiDocument* pUiDoc = pCurrentView->GetUiDocument();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pUiDoc, L"pUiDoc为空",L"GDMPLab",L"2024-03-30");
    IDocument* pDoc = pUiDoc->GetDbDocument();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");
    if (m_isUserCancelled)
    {
        // 如果用户选择退出
        UserTransactionGroupUtils::Abort(pDoc, m_nTransactionGroupId);
        m_nTransactionGroupId = -1;
        MarkFinishStatus(ActionFinishStatus::Successful);
        return;
    }
    else
    {
        OwnerPtr<IUserTransaction> utMove = IUserTransaction::Create(pDoc, GBMP_TR(L"对象移动"));
        if (m_eWayToSetup == EWS_On_Workplane)
        {
            gcmp::IModelView* pModelView = pCurrentView->GetModelView();
            DBG_WARN_AND_RETURN_VOID_UNLESS(pModelView, L"pModelView为空",L"GDMPLab",L"2024-03-30");
            OwnerPtr<IPlane> opPlane = pModelView->GetWorkPlane();
            DBG_WARN_AND_RETURN_VOID_UNLESS(opPlane, L"opPlane为空",L"GDMPLab",L"2024-03-30");
            OwnerPtr<IGraphicsPlane> opGPlane = IGraphicsPlane::CreateByDirections(opPlane->GetOrigin(), opPlane->GetDirectionU(), opPlane->GetDirectionV());
            MoveInstanceOnPlane(pDoc, m_placePt, opGPlane.get(), pCurrentView);
        }
        else
        {
            DBG_WARN_AND_RETURN_VOID_UNLESS((int)m_pickedNodes.size() == 1, L"pCurrentView为空",L"GDMPLab",L"2024-03-30");
            IReferencePlane *pRefPlane = IReferencePlane::CreateByGraphicsNodeReference(pDoc, *m_pickedNodes.at(0));
            pRefPlane->SetReferencePlaneType(ReferencePlaneType::Aided);
            DBG_WARN_AND_RETURN_VOID_UNLESS(pRefPlane != nullptr, L"参考平面创建不成功",L"GDMPLab",L"2024-03-30");
            gcmp::IElementBasicInformation* pElementBasicInformation = pRefPlane->GetBasicInformation();
            DBG_WARN_AND_RETURN_VOID_UNLESS(pElementBasicInformation, L"pElementBasicInformation为空",L"GDMPLab",L"2024-03-30");
            SetWorkPlaneForInstance(pDoc, pElementBasicInformation->GetElementId());
            const IPlane *pPlane = pRefPlane->GetGeometryPlane();
            DBG_WARN_AND_RETURN_VOID_UNLESS(pPlane != nullptr, L"参考平面创建不成功",L"GDMPLab",L"2024-03-30");
            OwnerPtr<IGraphicsPlane> opGPlane = IGraphicsPlane::CreateByDirections(pPlane->GetOrigin(), pPlane->GetDirectionU(), pPlane->GetDirectionV());
            MoveInstanceOnPlane(pDoc, GetMousePointOnPlane(pCurrentView, opGPlane.get(), m_placePt), opGPlane.get(), pCurrentView);
        }
        utMove->Commit();
        IHighlights::Get()->Clear();
        OwnerPtr<IUserTransaction> utShow = IUserTransaction::Create(pDoc, GBMP_TR(L"显示隐藏对象"));
        IInstance* instance = dynamic_cast<IInstance*>(pDoc->GetElement(m_idNewInstance));
        DBG_WARN_AND_RETURN_VOID_UNLESS(instance, L"Element为空",L"GDMPLab",L"2024-03-30");
        instance->GetStatus()->SetIsVisible(true);

        instance->SetExpandSubInstances(true);

        utShow->Commit();
        UserTransactionGroupUtils::CommitLatestActiveWithTransactionsMergedIntoOne(pDoc);
    }

    m_nTransactionGroupId = -1;
    m_idNewInstance = ElementId::InvalidID;
    UpdateView();

    //属于业务啦，不做处理,需要模块负责人自己决定行为
    //UIDocUtil::UpdatePropertyPanel();

    SelectPosition(pCurrentView);
}
void ActionCreatePointFamilyInstance::SelectPosition(gcmp::IUiView* pCurrentView)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(nullptr != pCurrentView, L"pCurrentView为空",L"GDMPLab",L"2024-03-30");
    IUiDocument* pUiDoc = pCurrentView->GetUiDocument();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pUiDoc, L"pUiDoc为空",L"GDMPLab",L"2024-03-30");
    IDocument* pDoc = pUiDoc->GetDbDocument();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDoc, L"无效的文档",L"GDMPLab",L"2024-03-30");
    CleanupTempGraphicsShape();
    UserTransactionGroupUtils::Start(pDoc, GBMP_TR(L"放置对象到"), m_nTransactionGroupId);
    OwnerPtr<IUserTransaction> ut = IUserTransaction::Create(pDoc, GBMP_TR(L"创建GBMP普通点式族实例"));
    IModelView* pModelView = pCurrentView->GetModelView();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pModelView, L"pModelView为空",L"GDMPLab",L"2024-03-30");
    ElementId baseId = GbmpModelViewUtil::GetReferencePlaneIdOfWorkPlane(pModelView);
    IReferencePlane* referencePlane = dynamic_cast<IReferencePlane*>(pDoc->GetElement(baseId));
    if (!baseId.GetIsValidId() || !referencePlane)
    {
        baseId = GetWorkLevelId(pDoc, pModelView);
    }
    Coordinate3d coord = GbmpModelViewUtil::GetWorkPlaneCoordinate(pModelView);
    OwnerPtr<IOnePointInstanceInput> opInput = IOnePointInstanceInput::Create(pDoc, baseId, m_familyId, m_familyType);
    IInstance* pInstance = IInstance::CreateByOnePoint(opInput.get(), false); 
    DBG_WARN_AND_RETURN_VOID_UNLESS(pInstance != nullptr, L"pInstance为空",L"GDMPLab",L"2024-03-30");

    pInstance->SetExpandSubInstances(false);

    m_idNewInstance = pInstance->GetBasicInformation()->GetElementId();
    pInstance->GetStatus()->SetIsVisible(false);
    if (!ut->Commit())
    {
        m_idNewInstance = ElementId::InvalidID;
        return;
    }
    if (m_eWayToSetup == EWS_On_Workplane)
    {
        SelectPositionOnWorkPlane();
    }
    else
    {
        SelectPositionOnFace(pDoc);
    }
}
void ActionCreatePointFamilyInstance::SelectPositionOnWorkPlane()
{
    SetPromptMessage(GBMP_TR(L"放置到工作平面：请输入对象的放置点"));
    m_isUserCancelled = false;
    gcmp::OwnerPtr<IPickPointAction> upPickPointAction(IPickPointAction::Create(
        PickPointExchangeData(&m_placePt, &m_isUserCancelled, &m_pickedPoints)
        , IPickPointAction::CreateMoveCallback(&ActionCreatePointFamilyInstance::PreviewOnWorkPlane, this)));
    StartChildAction(TransferOwnership(upPickPointAction));
}
void ActionCreatePointFamilyInstance::SelectPositionOnFace(gcmp::IDocument* pDoc)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");
    SetPromptMessage(GBMP_TR(L"放置到面：请输入对象的放置点"));
    m_isUserCancelled = false;

    gcmp::OwnerPtr<SetupRelatedPlanePickFaceFilter> upPickFilter = NEW_AS_OWNER_PTR(SetupRelatedPlanePickFaceFilter, pDoc);
    std::vector<ElementId> vecDisableIds;
    vecDisableIds.push_back(m_idNewInstance);
    upPickFilter->SetDisabledElements(vecDisableIds);

    PickNodeReferenceOption options;
    options.SetCursorType(GetCursorType());
    gcmp::OwnerPtr<IAction> upPickNodeReferenceAction
        = IPickNodeReferenceAction::Create(PickNodeReferenceExchangeData(true, &m_pickedNodes, &m_isUserCancelled, &m_placePt), TransferOwnership(upPickFilter), options);
    IPickNodeReferenceAction::CreateMoveCallback(&ActionCreatePointFamilyInstance::PreviewOnFace, this);

    StartChildAction(TransferOwnership(upPickNodeReferenceAction));
}
void ActionCreatePointFamilyInstance::PreviewOnFace(gcmp::IUiView* pCurrentView, const gcmp::Vector3d& mousePt)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(nullptr != pCurrentView, L"pCurrentView为空",L"GDMPLab",L"2024-03-30");
    IUiDocument* pUiDoc = pCurrentView->GetUiDocument();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pUiDoc, L"pUiDoc为空",L"GDMPLab",L"2024-03-30");
    IDocument* pDoc = pUiDoc->GetDbDocument();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDoc, L"无效的文档",L"GDMPLab",L"2024-03-30");

    CleanupTempGraphicsShape();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pCurrentView != nullptr, L"当前pCurrentView为空",L"GDMPLab",L"2024-03-30");
    const GraphicsNodeReferenceOwnerPtrVector& vecCandidates = IPickCandidates::Get()->GetCurrentPick()->GetAllGraphicsNodeReferences();
    if ((int)vecCandidates.size() != 1)
    {
        UpdateView();
        return;
    }

    OwnerPtr<IUserTransaction> ut = IUserTransaction::Create(pDoc, GBMP_TR(L"创建参照平面"));
    {
        IReferencePlane *pRefPlane = IReferencePlane::CreateByGraphicsNodeReference(pDoc, *vecCandidates.at(0));
        pRefPlane->SetReferencePlaneType(ReferencePlaneType::Aided);
        DBG_WARN_AND_RETURN_VOID_UNLESS(pRefPlane != nullptr, L"当前pCurrentView为空",L"GDMPLab",L"2024-03-30");
        SetWorkPlaneForInstance(pDoc, pRefPlane->GetBasicInformation()->GetElementId());
        const IPlane *pPlane = pRefPlane->GetGeometryPlane();
        OwnerPtr<IGraphicsPlane> opGPlane = IGraphicsPlane::CreateByDirections(pPlane->GetOrigin(), pPlane->GetDirectionU(), pPlane->GetDirectionV());
        DBG_WARN_AND_RETURN_VOID_UNLESS(opGPlane, L"graphicPlane为空",L"GDMPLab",L"2024-03-30");
        MoveInstanceOnPlane(pDoc, GetMousePointOnPlane(pCurrentView, opGPlane.get(), mousePt), opGPlane.get(), pCurrentView);
        Vector3d pointOnPlane = GetMousePointOnPlane(pCurrentView, opGPlane.get(), mousePt);
        IModelView* pModelView = pCurrentView->GetModelView();
        PreviewInstanceMoveOnPlane(pDoc, pointOnPlane, opGPlane.get(), pModelView);
    }
    ut->Rollback();
}

void ActionCreatePointFamilyInstance::PreviewOnWorkPlane(IUiView* pCurrentView, const gcmp::Vector3d& pos, const gcmp::Vector3d& mousePt)
{
    CleanupTempGraphicsShape();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pCurrentView != nullptr, L"当前pCurrentView为空",L"GDMPLab",L"2024-03-30");
    IModelView* pModelView = pCurrentView->GetModelView();
    OwnerPtr<IPlane> opPlane = pModelView->GetWorkPlane();
    OwnerPtr<IGraphicsPlane> opGPlane = IGraphicsPlane::CreateByDirections(opPlane->GetOrigin(), opPlane->GetDirectionU(), opPlane->GetDirectionV());
    PreviewInstanceMoveOnPlane(pModelView->GetDocument(), pos, opGPlane.get(), pModelView);
}

void ActionCreatePointFamilyInstance::MoveInstanceOnPlane(gcmp::IDocument* pDoc, const Vector3d& targetPt, gcmp::IGraphicsPlane* pPlane , IUiView* pCurrentView)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");
    DBG_WARN_AND_RETURN_VOID_UNLESS(pPlane, L"当前pPlane为空",L"GDMPLab",L"2024-03-30");
    IInstance *pInstance = dynamic_cast<IInstance*>(pDoc->GetElement(m_idNewInstance));
    DBG_WARN_AND_RETURN_VOID_UNLESS(pInstance != nullptr, L"Element为空",L"GDMPLab",L"2024-03-30");
    Vector3d ptCenter;
    if (const IElementPositionPoints* pCtrlPtBehavior = pInstance->GetPositionPoints())
    {
        if (!AlgorithmProject::Project(pCtrlPtBehavior->GetControlPoint(0), pPlane->GetGmIPlane(), Vector2d(), ptCenter))
            DBG_WARN_AND_RETURN_VOID_UNLESS(ptCenter.IsValid(), L"没有获得有效投影点",L"GDMPLab",L"2024-03-30");
    }
    Vector3d ptNewCenter;
    if (!AlgorithmProject::Project(targetPt, pPlane->GetGmIPlane(), Vector2d(), ptNewCenter))
        DBG_WARN_AND_RETURN_VOID_UNLESS(ptNewCenter.IsValid(), L"没有获得有效投影点",L"GDMPLab",L"2024-03-30");
    //MoveUtils将来会移到public内，暂时注释掉，不然会检测不通过
    GbmpMoveUtils::MoveElement(pInstance, ptCenter, ptNewCenter - ptCenter, pCurrentView->GetModelView());
    gcmp::IDocument* pDocument = pInstance->GetDocument();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDocument, L"pDocument为空",L"GDMPLab",L"2024-03-30");
    gcmp::IRegenerator* pRegenerator = pDocument->GetRegenerator();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pRegenerator, L"pRegenerator为空",L"GDMPLab",L"2024-03-30");
    pRegenerator->RegenerateElement(pInstance->GetElementId());
}
void ActionCreatePointFamilyInstance::SetWorkPlaneForInstance(gcmp::IDocument* pDoc, const gcmp::ElementId& idPlane)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");
    const GraphicsNodeReferenceOwnerPtrSet& selectedObjs = ISelection::Get()->GetGraphicsNodeReferences();
    IInstance *pInstance = dynamic_cast<IInstance*>(pDoc->GetElement(m_idNewInstance));//DocUtil::GetElement<IInstance>(pDoc, m_idNewInstance);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pInstance != nullptr, L"当前pInstance为空",L"GDMPLab",L"2024-03-30");
    IElementPosition *posBehavior = pInstance->GetElementPosition();
    if (posBehavior != nullptr)
    {
        posBehavior->SetBaseAssociatedPlaneId(idPlane);
    }
}
void ActionCreatePointFamilyInstance::PreviewInstanceMoveOnPlane(gcmp::IDocument* pDoc, const gcmp::Vector3d& targetPt, gcmp::IGraphicsPlane* pPlane, gcmp::IModelView* pModelView)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");
    DBG_WARN_AND_RETURN_VOID_UNLESS(pPlane, L"当前pPlane为空",L"GDMPLab",L"2024-03-30");
    OwnerPtr<IGraphicsElementShape> tempGrep = IGraphicsElementShape::Create(GraphicsRenderLayer::TransientObject);
    //GRepUtils::TransferGRepToGGroup需要外部自己封装实现一下///////
    //OwnerPtr<IGraphicsNodeGroup> pTempGpGrep = gcmp::GRepUtils::TransferGRepToGGroup(TransferOwnership(tempGrep));
    OwnerPtr<IGraphicsNodeGroup> pTempGpGrep = IGraphicsNodeGroup::Create();
    pTempGpGrep->GetChildrenFw().swap(tempGrep->GetChildrenFw());
    pTempGpGrep->SetGraphicsStyleId(tempGrep->GetGraphicsStyleId());
    pTempGpGrep->SetGraphicsMaterialId(tempGrep->GetGraphicsMaterialId());
    pTempGpGrep->SetFlags(tempGrep->GetFlags());
    pTempGpGrep->SetVisibility(tempGrep->GetVisibility());
    //////////////////////////////////////////////////////////////

    const IElement* pElement = pDoc->GetElement(m_idNewInstance);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pElement != nullptr, L"当前pElement为空",L"GDMPLab",L"2024-03-30");

    const IElementModelShape* pModelShape = pElement->GetElementModelShape();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pModelShape != nullptr, L"当前pModelShape为空",L"GDMPLab",L"2024-03-30");
    const IGraphicsElementShape* pGrep = pModelShape->GetGraphicsElementShape();

    const IInstance* pInstance = dynamic_cast<const IInstance*>(pElement);
    OwnerPtr<IGraphicsElementShape> opGrep = nullptr;
    if ((pInstance != nullptr)
        && (opGrep = pInstance->GetModelViewGRep(pModelView)))
    {
        pTempGpGrep->AddChild(TransferOwnership(opGrep));
        // 可能是GInstance, 因为GInstance所在Grep有且只能有一个子节点，所以这里克隆一份原始数据出来
        auto& opBodyVec = GbmpGraphicsNodeUtils::GetGRepBodies(pDoc, pGrep);
        for (int i = 0; i < opBodyVec.size(); ++i)
        {
            if (!opBodyVec[i].get())
                continue;

            pTempGpGrep->AddChild(TransferOwnership(opBodyVec[i]));
        }
    }
    else 
    {
        if (pGrep != nullptr)
        {
            int childCnt = pGrep->GetChildrenCount();
            for (int i = 0; i < childCnt; ++i)
            {
                if (!pGrep->GetChild(i))
                    continue;

                pTempGpGrep->AddChild(pGrep->GetChild(i)->Clone());
            }
        }
    }
    pTempGpGrep->SetGraphicsStyleId(pDoc->GetGraphicsStyleManager()->GetGraphicsStyleIdByCategoryUid(BuiltInCategoryUniIdentities::BICU_TEMP_STYLE));
    Vector3d ptCenter;
    if (const IElementPositionPoints* pCtrlPtBehavior = pElement->GetPositionPoints())
    {
        if (!AlgorithmProject::Project(pCtrlPtBehavior->GetControlPoint(0), pPlane->GetGmIPlane(), Vector2d(), ptCenter))
            DBG_WARN_AND_RETURN_VOID_UNLESS(ptCenter.IsValid(), L"没有获得有效投影点",L"GDMPLab",L"2024-03-30");
    }

    Vector3d ptNewCenter;
    if (!AlgorithmProject::Project(targetPt, pPlane->GetGmIPlane(), Vector2d(), ptNewCenter))
        DBG_WARN_AND_RETURN_VOID_UNLESS(ptNewCenter.IsValid(), L"没有获得有效投影点",L"GDMPLab",L"2024-03-30");
    Matrix4d mat;
    mat.MakeTranslate(ptNewCenter - ptCenter);
    pTempGpGrep->Transform(mat);
    DrawTempGraphicsNodeGroup(TransferOwnership(pTempGpGrep));
    UpdateView();
}


